package com.yami.shop.listener;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yami.shop.bean.enums.AirdropRecordEnum;
import com.yami.shop.bean.enums.EsOperationType;
import com.yami.shop.bean.event.AirDropSuccessEvent;
import com.yami.shop.bean.event.EsProductUpdateEvent;
import com.yami.shop.bean.event.QualificationEvent;
import com.yami.shop.bean.model.BusinessNft;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.UserAirdrop;
import com.yami.shop.bean.param.SendUserDropsParam;
import com.yami.shop.bean.vo.EsProdUpdateVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.service.BusinessNftService;
import com.yami.shop.service.ChannelUserRelationRecordService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.UserAirdropService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Component("prodDropListener")
@AllArgsConstructor
public class DropProdListener {

    private final ProductService productService;

    private final UserAirdropService userAirdropService;

    private final BusinessNftService businessNftService;

    private final ApplicationEventPublisher eventPublisher;

    private final ChannelUserRelationRecordService channelUserRelationRecordService;

    /**
     * 空投商品
     *
     * @param event event
     */
    @EventListener(AirDropSuccessEvent.class)
    @Transactional
    public void prodDropListener(AirDropSuccessEvent event) {
        if (ObjectUtil.isEmpty(event.getDrops()) || event.getType() == AirdropRecordEnum.BOX.value() || event.getType() == AirdropRecordEnum.BOX_PRIORITY.value()) {
            return;
        }
        for (String userId : event.getUserIds()) {
            List<EsProdUpdateVO> prodList = new ArrayList<>();
            for (SendUserDropsParam drop : event.getDrops()) {
                Long prodId = drop.getTargetId();
                Integer prodNums = drop.getNums();
                // 查询商品是否有库存
                Product productInfo = productService.getProductInfo(prodId);

                UserAirdrop record = new UserAirdrop();
                record.setAirDropId(IdUtil.getSnowflakeNextId());
                record.setArticleName(productInfo.getProdName());
                record.setArticleId(prodId.toString());
                record.setArticleType(drop.getType());
                record.setUserId(userId);
                record.setNum(prodNums);
                record.setBusinessType(event.getBusinessType());
                record.setCreateTime(new Date());
                record.setDropShopId(event.getShopId());
                record.setAirdropBusinessId(event.getAirdropBusinessId());
                if (drop.getType() == 0) {
                    // 空投商品
                    // 更新es中的商品库存
                    EsProdUpdateVO esProdUpdateVO = new EsProdUpdateVO();
                    esProdUpdateVO.setProdId(prodId);
                    esProdUpdateVO.setCount(prodNums);
                    esProdUpdateVO.setType(0);
                    prodList.add(esProdUpdateVO);
                    eventPublisher.publishEvent(new EsProductUpdateEvent(prodId, null, EsOperationType.UPDATE));
                    productService.removeProdCacheByProdId(prodId);
                    // 更新es中的商品库存--更新失败打印日志，优先保证订单流程没问题
                    try {
                        eventPublisher.publishEvent(new EsProductUpdateEvent(prodList, EsOperationType.UPDATE_ORDER_STOCK_NUM_BATCH));
                    } catch (Exception e) {
                        log.error("提交订单-更新es商品库存失败，错误为：{}", e);
                        throw new YamiShopBindException("【" + productInfo.getProdName() + "】更新es商品库存失败");
                    }
                    if (productInfo.getTotalStocks() == 0) {
                        // 库存不足
                        record.setStatus(AirdropRecordEnum.FAIL.value());
                        record.setReason("【" + productInfo.getProdName() + "】商品库存不足");
                        userAirdropService.save(record);
                        throw new YamiShopBindException("【" + productInfo.getProdName() + "】商品库存不足");
                    }
                    // 判断用户是否有链上地址的
//                    if (!channelUserRelationRecordService.isHasDTCAddress(userId, productInfo.getChain(), productInfo.getChannelCode())) {
//                        record.setStatus(AirdropRecordEnum.FAIL.value());
//                        record.setReason("未查询到空投用户的链上地址");
//                        userAirdropService.save(record);
//                        continue;
//                    }
                    record.setStatus(AirdropRecordEnum.WAIT.value());
                    userAirdropService.save(record);
                    saveBusinessNft(userId, prodNums, record,event.getMainProdId());
                }
                if (drop.getType() == 2) {
                    // 空投商品优先购资格
                    eventPublisher.publishEvent(new QualificationEvent(userId, prodId, null, prodNums.longValue(), 1L, 2,record.getAirDropId().toString(),ObjectUtil.isNotNull(drop.getEffectiveTime()) ? drop.getEffectiveTime() : null ));
                    record.setStatus(AirdropRecordEnum.SUCCESS.value());
                    record.setSuccessNum(prodNums);
                    userAirdropService.save(record);
                }
            }
        }
    }

    /**
     * 保存空投数据到取币业务表，等待取币
     *
     * @param userId   userId
     * @param prodNums prodNums
     * @param record   record
     */

    private void saveBusinessNft(String userId, Integer prodNums, UserAirdrop record,Long mainProdId) {
        BusinessNft businessNft = new BusinessNft();
        businessNft.setOutId(record.getAirDropId().toString());
        businessNft.setBusinessType(9);
        businessNft.setProdName(record.getArticleName());
        businessNft.setProdId(record.getArticleId());
        businessNft.setUserId(userId);
        businessNft.setNum(prodNums);
        businessNft.setStatus(0);
        businessNft.setCreateTime(new Date());
        businessNftService.save(businessNft);
    }

}
